package com.joinway.framework.admin.core.service

import java.util.List;

import org.apache.commons.collections4.CollectionUtils
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service

import com.joinway.framework.admin.bean.domain.AdminUserRole
import com.joinway.framework.admin.bean.domain.RoleTreeMenu
import com.joinway.framework.admin.bean.domain.TreeMenu
import com.joinway.framework.admin.bean.view.LoginRole
import com.joinway.framework.admin.core.bean.view.Menu
import com.joinway.framework.bean.domain.constant.DomainConstants
import com.joinway.framework.core.utils.AppEnv
import com.joinway.framework.data.jdbc.repository.TableRepository

@Service
class AdminQueryService {

	private final static Logger log = LoggerFactory.getLogger(AdminQueryService.class)
	
	@Autowired protected TableRepository repository;

	List<LoginRole> findLoginRoles(int userId){
		String sql = """
			select aur.role_id roleId
				, ar.role_name roleName 
				, ar.description roleDesc
			from admin_user_role aur 
				left join admin_role ar on aur.role_id = ar.id
				right join admin_user au on au.id = aur.user_id		
			where au.id = ? and ar.status = ? and (ar.app_id = ? or ar.app_id is null or length(trim(ar.app_id)) = 0)
"""
		repository.find(LoginRole, sql, userId, DomainConstants.YES, AppEnv.getAppId())
	} 
	
	List<String> findRoleNames(int userId){
		String sql = """
		select upper(role_name) roleName from admin_role ar
			left join admin_user_role aur on ar.id = aur.role_id
		where aur.user_id = ?
"""
		List roleNames = []
		repository.find(sql, userId).each {
			roleNames.add(it.roleName)
		}
		
		roleNames
	}
	
	public List<TreeMenu> findTreeMenus() throws Exception {
		repository.find(TreeMenu, "select * from tree_menu")
	}
	
	public List<TreeMenu> findTreeMenus(int userId) throws Exception {
		List<TreeMenu> userTrees = new ArrayList<>();
		
		String sql = """
		select t.* from tree_menu t
			right join admin_role_menu arm on arm.menu_id = t.id
			right join admin_user_role aur on aur.role_id = arm.role_id
			right join admin_role ar on aur.role_id = ar.id
			right join admin_user au on au.id = aur.user_id
		where t.status = ?
			and au.id = ?
			and ar.status = ?
			and t.app_id = ?
"""
		
		List<TreeMenu> trees = repository.find(TreeMenu, sql, DomainConstants.YES, userId, DomainConstants.YES, AppEnv.getAppId())
		
		// add parent menu
		List<TreeMenu> allTrees = repository.findAll(TreeMenu);
		
		Set<TreeMenu> tms = new HashSet<>();

		for(TreeMenu tm : trees){
			if(tm.getParentId() == 0){
				// self is parent menu, add it
				tms.add(tm);
			}
		}
		
		fillParentMenus(tms, trees, allTrees);
		
		if(CollectionUtils.isNotEmpty(tms)){
			tms.addAll(trees);
			
			userTrees.addAll(tms);
		}
		
		return userTrees;
	}
	
	public List<RoleTreeMenu> findRoleTreeMenus(String roleId) throws Exception {
		String sql = """
		select distinct
			tm.* 
			, if(arm.menu_id, 'Y', 'N') owned
		from tree_menu tm
			left join admin_role_menu arm on arm.menu_id = tm.id
"""
		List params = []
		
		if(roleId){
			sql += " and arm.role_id = ?"
			params << roleId
		}
		
		sql += " where tm.app_id = ?"
		params << AppEnv.getAppId()
		
		List<RoleTreeMenu> roleMenus = repository.find(RoleTreeMenu, sql, params)

		return roleMenus
	}
	
	public List<AdminUserRole> findAdminUserRoles(int userId){
		String appId = AppEnv.getAppId();
		String sql = """
		select * from admin_user_role aur
			join admin_user au on aur.user_id = au.id
			join admin_role ar on aur.role_id = ar.id
		where
			aur.user_id = ? and ar.app_id = '$appId'
"""
		return repository.find(AdminUserRole, sql, userId)
	}
	
	public List<Menu> findUserRoleMenuList(List<Integer> roleIds = null){
		String appId = AppEnv.getAppId();
		String sql
		
		if(roleIds){
			String ids = roleIds.iterator().join(",")
			sql = """
		select distinct tm.* from tree_menu tm 
			right join admin_role_menu arm on tm.id = arm.menu_id 
		where tm.app_id = '$appId' and role_id in ($ids)
"""
		}else{
			sql = "select distinct tm.* from tree_menu tm where tm.app_id = '$appId' "
		}
		
		sql += " order by tm.id"
		
		return repository.find(Menu, sql);
	}
	
	protected void fillParentMenus(Set<TreeMenu> parentMenus, List<TreeMenu> currentMenus, List<TreeMenu> allTrees) throws Exception {
		if(CollectionUtils.isNotEmpty(currentMenus)){
			for(TreeMenu tm : currentMenus){
				List<TreeMenu> m = allTrees.findAll{it.id == tm.getParentId()};//Filter.create(allTrees, Condition.create("id", tm.getParentId())).result();
				
				if(CollectionUtils.isNotEmpty(m)){
					parentMenus.addAll(m);
				}
				
				fillParentMenus(parentMenus, m, allTrees);
			}
		}
	}

}
